Compiled date: 2021-09-07

Last edited: 2021-09-07

1 Loading required packages

library("DESeq2")
library("topGO")
library("org.Mm.eg.db")
library("pcaExplorer")
library("ideal")
library("GeneTonic")

2 Introductory Paragraph

pcaExplorer is a Bioconductor package [https://doi.org/10.1186/gb-2004-5-10-r80] which can be seen as a general-purpose interactive companion tool for RNA-seq analyses. pcaExplorer is designed to guide the user in exploring the Principal Components (PC) [https://doi.org/10.2307/1270093] of the data under inspection. Besides the Principal Component Analysis (PCA) [https://doi.org/10.2307/1270093], pcaExplorer also provides tools to detect outlier samples, genes that show particular patterns and additionally provides a functional interpretation of the principal components for further quality assessment and hypothesis generation on the input data.

In this protocol we describe how to launch a Shiny application [https://CRAN.R-project.org/package=shiny] of pcaExplorer with the data of the macrophage dataset [https://doi.org/10.1038/s41588-018-0046-7] which is also distributed via Bioconductor [https://doi.org/10.1186/gb-2004-5-10-r80].

3 Necessary Resources

Hardware

a modern desktop computer or laptop with any up-to-date operating system

Software

R 3.3 or higher, Bioconductor 3.3 or higher, (optional?) RStudio, optional browser to open vignettes

Files (maybe we can describe the sample input here and how to download from Github, I’ve seen that in some papers rather than describing the general input format)

pcaExplorer mainly requires 3 input files in text format. The files are expected to be tab-separated, but also comma- or semicolon-separated files are accepted (see Alternative protocol 1). The first input file is the count matrix which stores the number of times (i.e counts) a certain feature (e.g gene) is found in each sample. In the count matrix, the samples are stored in the columns, while the rows store the individual features (see Fig. 1).

Figure 1 Example of a count matrix - The figure shows the example of a count matrix, with the individual features (here genes) in the rows and the individual samples in the columns. The matrix represents how many times each feature was found in each sample. The shown count matrix is comma-separated, but also semicolon- and tab-separated inputs are accepted (see Alternative protocol 1)

The second input of pcaExplorer is the metadata file. This file stores for each sample the necessary experimental variables. The individual samples represent the rows of the file while the columns save the different experimental variables (see Fig. 2).

Figure 2 Example of a Metadata file - The figure shows the example of a Metadata file. The rows of the file contain the individual samples while the columns represent relevant experimental variables. The variable can change depending on the data set and research question. Lastly, the third input of pcaExplorer is optional, but highly recommended for an ease of interpretation of the results. The last input is the annotation file. The file contains the feature ids of the count matrix in the rows and at least one column called gene name which contains a more human readable form of the feature ids (e.g. HGNC gene names [https://doi.org/10.1093/nar/gkaa980] if the features are gene ids). Fig. 3 shows an example of an annotation file.

Figure 3 Example of an annotation file - The annotation file contains a row for each of the features of the count matrix. Furthermore, the file contains at least one column called gene names which contains a more human readable for of the feature identifiers of the rows. In the shown example the feature ids are ENSEMBL ids while the column gene names contains HGNC gene names.

Exploring the data with pcaExplorer

Before we start with the exploration of the data, the necessary packages and dependencies need to be installed and loaded. Support Protocol 1 describes how to install and load the packages.

  1. Prepare the input data. Launch the Shiny application with the command pcaExplorer(countmatrix, metadata, annotation) where countmatrix, metadata and annotation have to be substituted by the file paths of the respective input files. To launch the application, enter the command into the console of RStudio and press the Enter-Button. This should launch a second window with the pcaExplorer application. In this application you should see the Data Upload panel as shown in Fig. 4.

Figure 4 Data Upload panel - The figure shows the Data Upload panel which is the first panel a user sees upon launching pcaExplorer. The panel provides previes on the input data as well as buttons to interact with the application.

  1. Click the “Generate the dds and dst object” button to generate the dds and dst object needed for the exploration of the data (Fig 4). Scroll down on the Data Upload panel. After the generation of the dds and dst object you should find the ‘Select one of the following transformations for your data:’ option with three blue colored buttons underneath. Each button describes a different transformation of the data. The first button on the far left ‘Compute variance stabilized transformed data from the dds object’ computes a variance stabilized transformed version on the data upon clicking the button. The middle button computes a regularized logarithm transformed version of the data, while the button on the far right computes log2 data. The choice of transformation of the data in this step should be dependent on the input data. If you follow this protocol using the provided sample data, click the ‘Compute variance stabilized transformed data from the dds object’ button on the far left.

  2. At the bottom of the Data Upload panel, a preview of the input data is provided. Here you’ll find four green colored buttons which provide a preview on the respective input data upon clicking.

  3. Navigate to the Counts Table panel through clicking on the panel name in the panel list at the beginning of each panel (Fig. 5). In this panel, the count information of the count matrix is shown in a table. A drop-down menu at the beginning of the panel provides the possibility to change the data scale in the table. Different options can be chosen through clicking (e.g. raw counts, normalized counts, regularized logarithm transformed counts, etc.). Users can download the counts table through clicking on the green download button below the table (Fig. 5).

Figure 5 Counts Table panel - The figure shows the Counts Table panel. This panel provides an overview of the input counts matrix.

  1. Scroll down until you see the ‘Sample to sample scatter plots’ heading (Fig. 5). Choose ‘pearson’ as correlation method from the ‘Correlation method palette’. Ensure that both options ‘Use log2 values for plot axes and values’ and ‘Use a subset of max 1000 genes (quicker to plot)’ are selected. An option is selected, if the small box in front of the option is ticked (Fig. 5). Click on the ‘Run’ button to generate the scatter plots.

  2. TODO: Something about the inspection of the plot and some general remarks to the type of plots

Figure 6

Figure 7 Sample to Sample similarity heatmap

  1. Navigate to the Data Overview panel through clicking on the panel name in the panel list at the beginning of each panel (Fig. 8). The panel shows the input metadata as table in the upper half of the panel. The number of entries shown in the table can be managed with the “Show X entries” drop down menu. Furthermore, in the right upper corner of the table, users can find a Search field, which can be used to search for specific terms in the metadata table (Fig. 8). Below the metadata table, a Sample to Sample distance heatmap can be found. This heatmap reflects the distances between the individual samples. The “Select the distance method to use” option enables users to change the distance method used for the heatmap. Furthermore, users have the option to download the heatmap via the “Download Plot” button in the lower right corner below the heatmap. In the field “Save as…” users can specify the name of the file to save the heatmap (Fig 8).

Figure 8

  1. Scroll down in the Data Overview panel. Below the heatmap, the panel provides further information about the input data (Fig. 9 & 10).

Figure 9

Figure 10

  1. Navigate to the Samples View panel through clicking on the panel name in the panel list at the beginning of each panel (Fig. 11). When directed to the panels, users see the PCA of the individual samples of the iput data on the left side with the corresponding scree plot shown on the right side. Initially the samples shown in the PCA are not colored by any group hence it is hard to identify the characteristics of the samples along which the PCA groups the samples. In the presented data, users should color the samples by condition. To color the samples by condition, click on the “Group/color by” filed on the grey side bar at the far left of the screen. Scroll down in the drop-down menu which opens upon clicking until you find the “condition” option. Click this option. It should now be displayed in the before empty field (Fig. 12). Furthermore, the PCA plot changed displaying the samples now in 4 colors compared to one before (Fig. 12). Users can also download the PCA plor via the “Download plot” button in the lower right corner of the plot. As seen before, users can specify the name of the file they want to save the plot. This is also possible for the Screeplot on the right side of the panel.

some notes about how to delete option, identifiy the right optio for you data and how to use the scree plot

Figure 11 The Samples View panel - This panel shows a PCA of the individual samples of the input data. In the upper part of the panel, the PCA on the samples and the corresponding scree plot are shown. Initially there is no grouping shown in the PCA.

Figure 12 PCA colored by condition - The PCA plot of the samples is shown colored by condition. This coloring is achieved by selecting the option “condition” in the “Group/color by” selection tab at the far left of the screen. The tab indicates the selected option by displaying the name of the option in the field. Users can remove options by clicking into the option field right behind the option to be deleted and hitting the delete key on the keyboard.

  1. The Sample View panel provides the possibility to zoom in on the PCA. For this, hover your mouse over the PCA plot until your mouse pointer changes to a little plus sign. Press the left button of the mouse and move the mouse to draw a little grey rectagle (Fig. 13). Move the mouse to the upper left corner of the PCA plot and select all samples belonging to the naive condition (colored in blue in Fig. 12) as explained before. After selecting the samples, scroll down in the panel until you see a zoomed in version of the PCA plot containing mainly the selected sampels. This should somewhat look like the plot shown in Fig. 13.

Figure 13 Zoomed in PCA plot - The figure shows the zooming mechanism on the PCA plot of the Samples View panel. The grey rectangle in the upper PCA plot indicates the portion of the PCA plot selected for zooming. This selected portion of the plot is shown in the lower PCA plot in more detail.

  1. The zoomed in PCA plot can be downloaded via the “Download plot” button in the lower right corner below the plot. As aforementioned the name of the file to save the plot can also be specified.

  2. Something about the plot on the right sied of the zoomed in PCA

  3. Scroll down in the Sample View panel until you see the “Outlier identification” option (Fig. 14). The “Select which sample(s) to remove - suspected outliers” options provides the possibility to select individual samples, which are suspected to be outliers, and remove them from the PCA. For demonstration purposes select all samples from the “naive” condition and remove them from the PCA (the sample ids end in “102”, “111”, “182”, “262”, “284” and “368”). To remove samples from the plot, click on the field below the “Select which sample(s) to remove - suspected outliers” option. This opens a drop-won menu with the sample ids of all samples listed. Select the above mentioned sample ids until the PCA plot looks like Fig. 15.

Something about the plot at the bottom of the panel and overall outlier identification

Figure 14 Outlier identification - The Samples View panel provides the possibility to detect outliers.

Figure 15 PCA plot with outliers removed - THe figures shows the PCA plot with all samples of the “naive” condition removed. With this type of sample selection, outlier samples in the data can be detected and removed from the PCA.

  1. Navigate to the “Intructions” panel through clicking on the panel name in the panel list at the beginning of each panel (Fig. 16). Open the vignettes of pcaExplorer by clicking on the two buttons “Open the User Guide (main vignette)” and “Open the ‘UP and Running’ vignette”. This will open the two vignettes of pcaExplorer in your selected default browser. The vignettes describe the individual panels of pcaExplorer in detail and provide walkthroughs on how to explore input data with pcaExplorer. Users are recommended to read the vignettes to fully graps the different possibilities provided with pcaExplorer.

Figure 16 Instructions panel

Session information

sessionInfo()
## R version 4.1.1 (2021-08-10)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 19042)
## 
## Matrix products: default
## 
## locale:
## [1] LC_COLLATE=German_Germany.1252  LC_CTYPE=German_Germany.1252    LC_MONETARY=German_Germany.1252
## [4] LC_NUMERIC=C                    LC_TIME=German_Germany.1252    
## 
## attached base packages:
## [1] parallel  stats4    stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] GeneTonic_1.4.1             ideal_1.16.0                pcaExplorer_2.18.0         
##  [4] org.Mm.eg.db_3.13.0         topGO_2.44.0                SparseM_1.81               
##  [7] GO.db_3.13.0                AnnotationDbi_1.54.1        graph_1.70.0               
## [10] DESeq2_1.32.0               SummarizedExperiment_1.22.0 Biobase_2.52.0             
## [13] MatrixGenerics_1.4.3        matrixStats_0.60.1          GenomicRanges_1.44.0       
## [16] GenomeInfoDb_1.28.2         IRanges_2.26.0              S4Vectors_0.30.0           
## [19] BiocGenerics_0.38.0         knitr_1.33                 
## 
## loaded via a namespace (and not attached):
##   [1] utf8_1.2.2               shinydashboard_0.7.1     tidyselect_1.1.1        
##   [4] heatmaply_1.2.1          RSQLite_2.2.8            htmlwidgets_1.5.3       
##   [7] grid_4.1.1               TSP_1.1-10               BiocParallel_1.26.2     
##  [10] IHW_1.20.0               munsell_0.5.0            codetools_0.2-18        
##  [13] DT_0.19                  rentrez_1.2.3            miniUI_0.1.1.1          
##  [16] withr_2.4.2              colorspace_2.0-2         Category_2.58.0         
##  [19] filelock_1.0.2           shinyWidgets_0.6.0       NMF_0.23.0              
##  [22] slam_0.1-48              GenomeInfoDbData_1.2.6   lpsymphony_1.20.0       
##  [25] polyclip_1.10-0          farver_2.1.0             bit64_4.0.5             
##  [28] pheatmap_1.0.12          vctrs_0.3.8              generics_0.1.0          
##  [31] xfun_0.25                BiocFileCache_2.0.0      R6_2.5.1                
##  [34] doParallel_1.0.16        clue_0.3-59              seriation_1.3.0         
##  [37] locfit_1.5-9.4           bitops_1.0-7             cachem_1.0.6            
##  [40] shinyAce_0.4.1           DelayedArray_0.18.0      assertthat_0.2.1        
##  [43] shinycssloaders_1.0.0    promises_1.2.0.1         BiocIO_1.2.0            
##  [46] scales_1.1.1             gtable_0.3.0             Cairo_1.5-12.2          
##  [49] rlang_0.4.11             genefilter_1.74.0        GlobalOptions_0.1.2     
##  [52] splines_4.1.1            rtracklayer_1.52.1       lazyeval_0.2.2          
##  [55] bs4Dash_2.0.2            shinyBS_0.61             BiocManager_1.30.16     
##  [58] yaml_2.2.1               reshape2_1.4.4           GenomicFeatures_1.44.2  
##  [61] threejs_0.3.3            crosstalk_1.1.1          httpuv_1.6.2            
##  [64] RBGL_1.68.0              backbone_1.5.0           tools_4.1.1             
##  [67] bookdown_0.24            gridBase_0.4-7           ggplot2_3.3.5           
##  [70] ellipsis_0.3.2           gplots_3.1.1             jquerylib_0.1.4         
##  [73] RColorBrewer_1.1-2       dynamicTreeCut_1.63-1    Rcpp_1.0.7              
##  [76] plyr_1.8.6               visNetwork_2.0.9         base64enc_0.1-3         
##  [79] progress_1.2.2           zlibbioc_1.38.0          purrr_0.3.4             
##  [82] RCurl_1.98-1.4           BiasedUrn_1.07           prettyunits_1.1.1       
##  [85] GetoptLong_1.0.5         viridis_0.6.1            ggrepel_0.9.1           
##  [88] cluster_2.1.2            magrittr_2.0.1           data.table_1.14.0       
##  [91] circlize_0.4.13          colourpicker_1.1.0       goseq_1.44.0            
##  [94] hms_1.1.0                mime_0.11                evaluate_0.14           
##  [97] xtable_1.8-4             XML_3.99-0.7             shape_1.4.6             
## [100] gridExtra_2.3            compiler_4.1.1           biomaRt_2.48.3          
## [103] tibble_3.1.4             KernSmooth_2.23-20       crayon_1.4.1            
## [106] htmltools_0.5.2          GOstats_2.58.0           mgcv_1.8-36             
## [109] later_1.3.0              tidyr_1.1.3              geneplotter_1.70.0      
## [112] expm_0.999-6             DBI_1.1.1                tweenr_1.0.2            
## [115] geneLenDataBase_1.28.0   ComplexHeatmap_2.8.0     dbplyr_2.1.1            
## [118] MASS_7.3-54              rappdirs_0.3.3           BiocStyle_2.20.2        
## [121] Matrix_1.3-4             igraph_1.2.6             pkgconfig_2.0.3         
## [124] GenomicAlignments_1.28.0 registry_0.5-1           plotly_4.9.4.1          
## [127] xml2_1.3.2               foreach_1.5.1            annotate_1.70.0         
## [130] bslib_0.3.0              rngtools_1.5             pkgmaker_0.32.2         
## [133] webshot_0.5.2            XVector_0.32.0           AnnotationForge_1.34.0  
## [136] stringr_1.4.0            digest_0.6.27            Biostrings_2.60.2       
## [139] rmarkdown_2.10           rintrojs_0.3.0           dendextend_1.15.1       
## [142] GSEABase_1.54.0          restfulr_0.0.13          curl_4.3.2              
## [145] shiny_1.6.0              Rsamtools_2.8.0          gtools_3.9.2            
## [148] rjson_0.2.20             lifecycle_1.0.0          nlme_3.1-152            
## [151] jsonlite_1.7.2           viridisLite_0.4.0        limma_3.48.3            
## [154] fansi_0.5.0              pillar_1.6.2             lattice_0.20-44         
## [157] KEGGREST_1.32.0          fastmap_1.1.0            httr_1.4.2              
## [160] survival_3.2-11          glue_1.4.2               fdrtool_1.2.16          
## [163] UpSetR_1.4.0             png_0.1-7                iterators_1.0.13        
## [166] bit_4.0.4                Rgraphviz_2.36.0         ggforce_0.3.3           
## [169] stringi_1.7.4            sass_0.4.0               blob_1.2.2              
## [172] caTools_1.18.2           memoise_2.0.0            dplyr_1.0.7
LS0tDQp0aXRsZTogPg0KICBCYXNpYyBQcm90b2NvbCAxOiBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzIHdpdGggcGNhRXhwbG9yZXINCmF1dGhvcjoNCi0gbmFtZTogQW5uZWthdGhyaW4gTHVkdA0KICBhZmZpbGlhdGlvbjogDQogIC0gJmlkMSBJbnN0aXR1dGUgb2YgTWVkaWNhbCBCaW9zdGF0aXN0aWNzLCBFcGlkZW1pb2xvZ3kgYW5kIEluZm9ybWF0aWNzIChJTUJFSSksIE1haW56DQogIGVtYWlsOiBhbm5lbHVkdEB1bmktbWFpbnouZGUNCi0gbmFtZTogQ2h1bmcgU2hpbmcgUmV4IEhhDQogIGFmZmlsaWF0aW9uOiANCiAgLSAqaWQxDQogIGVtYWlsOiByZXhoYUB1bmktbWFpbnouZGUNCi0gbmFtZTogSGFyYWxkIEJpbmRlcg0KICBhZmZpbGlhdGlvbjoNCiAgLSBJbnN0aXR1dGUgb2YgTWVkaWNhbCBCaW9tZXRyeSBhbmQgU3RhdGlzdGljcyAoSU1CSSksIEZhY3VsdHkgb2YgTWVkaWNpbmUgYW5kIE1lZGljYWwgQ2VudGVyLCBVbml2ZXJzaXR5IG9mIEZyZWlidXJnIA0KICBlbWFpbDogYmluZGVyQGltYmkudW5pLWZyZWlidXJnLmRlIA0KLSBuYW1lOiBLb25zdGFudGluIFN0cmF1Y2gNCiAgYWZmaWxpYXRpb246IA0KICAtICppZDENCiAgZW1haWw6IHN0cmF1Y2hAdW5pLW1haW56LmRlDQotIG5hbWU6IEZlZGVyaWNvIE1hcmluaQ0KICBhZmZpbGlhdGlvbjogDQogIC0gKmlkMQ0KICAtICZpZDIgQ2VudGVyIGZvciBUaHJvbWJvc2lzIGFuZCBIZW1vc3Rhc2lzIChDVEgpLCBNYWluejs8YnI+DQogIGVtYWlsOiBtYXJpbmlmQHVuaS1tYWluei5kZQ0KZGF0ZTogImByIEJpb2NTdHlsZTo6ZG9jX2RhdGUoKWAiDQpwYWNrYWdlOiAiYHIgQmlvY1N0eWxlOjpwa2dfdmVyKCdpZGVhbCcpYCINCm91dHB1dDogDQogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoNCiAgIyBCaW9jU3R5bGU6Omh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdGhlbWU6IGNvc21vDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQ0KIyBiaWJsaW9ncmFwaHk6IGlkZWFsX3N1cHBsLmJpYg0KbGluay1jaXRhdGlvbnM6IHRydWUNCi0tLQ0KDQoqKkNvbXBpbGVkIGRhdGUqKjogYHIgU3lzLkRhdGUoKWANCg0KKipMYXN0IGVkaXRlZCoqOiBgciBTeXMuRGF0ZSgpYA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFLCBjYWNoZSA9IEZBTFNFLCBldmFsID0gVFJVRSwgZWNobyA9IEZBTFNFfQ0KbGlicmFyeShrbml0cikNCm9wdHNfY2h1bmskc2V0KA0KICBmaWcuYWxpZ24gPSAiY2VudGVyIiwNCiAgZmlnLnNob3cgPSAiYXNpcyIsDQogIGV2YWwgPSBUUlVFLA0KICBmaWcud2lkdGggPSAxMCwNCiAgZmlnLmhlaWdodCA9IDcsDQogIHRpZHkgPSBGQUxTRSwNCiAgbWVzc2FnZSA9IEZBTFNFLA0KICB3YXJuaW5nID0gRkFMU0UsDQogIHNpemUgPSAic21hbGwiLA0KICBjb21tZW50ID0gIiMjIiwNCiAgZWNobyA9IFRSVUUsDQogIHJlc3VsdHMgPSAibWFya3VwIg0KKQ0Kb3B0aW9ucyhyZXBsYWNlLmFzc2lnbiA9IFRSVUUsIHdpZHRoID0gMTAwKQ0KYGBgDQoNCiMgTG9hZGluZyByZXF1aXJlZCBwYWNrYWdlcw0KDQpgYGB7ciBsb2FkTGlicmFyaWVzLCByZXN1bHRzPSAiaGlkZSJ9DQpsaWJyYXJ5KCJERVNlcTIiKQ0KbGlicmFyeSgidG9wR08iKQ0KbGlicmFyeSgib3JnLk1tLmVnLmRiIikNCmxpYnJhcnkoInBjYUV4cGxvcmVyIikNCmxpYnJhcnkoImlkZWFsIikNCmxpYnJhcnkoIkdlbmVUb25pYyIpDQpgYGANCg0KDQojIEludHJvZHVjdG9yeSBQYXJhZ3JhcGgNCnBjYUV4cGxvcmVyIGlzIGEgQmlvY29uZHVjdG9yIHBhY2thZ2UgW2h0dHBzOi8vZG9pLm9yZy8xMC4xMTg2L2diLTIwMDQtNS0xMC1yODBdIHdoaWNoIGNhbiBiZSBzZWVuIGFzIGEgZ2VuZXJhbC1wdXJwb3NlIGludGVyYWN0aXZlIGNvbXBhbmlvbiB0b29sIGZvciBSTkEtc2VxIGFuYWx5c2VzLiBwY2FFeHBsb3JlciBpcyBkZXNpZ25lZCB0byBndWlkZSB0aGUgdXNlciBpbiBleHBsb3JpbmcgdGhlIFByaW5jaXBhbCBDb21wb25lbnRzIChQQykgW2h0dHBzOi8vZG9pLm9yZy8xMC4yMzA3LzEyNzAwOTNdIG9mIHRoZSBkYXRhIHVuZGVyIGluc3BlY3Rpb24uIEJlc2lkZXMgdGhlIFByaW5jaXBhbCBDb21wb25lbnQgQW5hbHlzaXMgKFBDQSkgW2h0dHBzOi8vZG9pLm9yZy8xMC4yMzA3LzEyNzAwOTNdLCBwY2FFeHBsb3JlciBhbHNvIHByb3ZpZGVzIHRvb2xzIHRvIGRldGVjdCBvdXRsaWVyIHNhbXBsZXMsIGdlbmVzIHRoYXQgc2hvdyBwYXJ0aWN1bGFyIHBhdHRlcm5zIGFuZCBhZGRpdGlvbmFsbHkgcHJvdmlkZXMgYSBmdW5jdGlvbmFsIGludGVycHJldGF0aW9uIG9mIHRoZSBwcmluY2lwYWwgY29tcG9uZW50cyBmb3IgZnVydGhlciBxdWFsaXR5IGFzc2Vzc21lbnQgYW5kIGh5cG90aGVzaXMgZ2VuZXJhdGlvbiBvbiB0aGUgaW5wdXQgZGF0YS4gDQoNCkluIHRoaXMgcHJvdG9jb2wgd2UgZGVzY3JpYmUgaG93IHRvIGxhdW5jaCBhIFNoaW55IGFwcGxpY2F0aW9uIFtodHRwczovL0NSQU4uUi1wcm9qZWN0Lm9yZy9wYWNrYWdlPXNoaW55XSBvZiBwY2FFeHBsb3JlciB3aXRoIHRoZSBkYXRhIG9mIHRoZSBtYWNyb3BoYWdlIGRhdGFzZXQgW2h0dHBzOi8vZG9pLm9yZy8xMC4xMDM4L3M0MTU4OC0wMTgtMDA0Ni03XSB3aGljaCBpcyBhbHNvIGRpc3RyaWJ1dGVkIHZpYSBCaW9jb25kdWN0b3IgW2h0dHBzOi8vZG9pLm9yZy8xMC4xMTg2L2diLTIwMDQtNS0xMC1yODBdLiANCg0KIyBOZWNlc3NhcnkgUmVzb3VyY2VzDQoNCipIYXJkd2FyZSoNCg0KICBhIG1vZGVybiBkZXNrdG9wIGNvbXB1dGVyIG9yIGxhcHRvcCB3aXRoIGFueSB1cC10by1kYXRlIG9wZXJhdGluZyBzeXN0ZW0NCiAgDQoqU29mdHdhcmUqDQoNCiAgUiAzLjMgb3IgaGlnaGVyLCBCaW9jb25kdWN0b3IgMy4zIG9yIGhpZ2hlciwgKG9wdGlvbmFsPykgUlN0dWRpbywgb3B0aW9uYWwgYnJvd3NlciB0byBvcGVuIHZpZ25ldHRlcw0KICANCipGaWxlcyogKG1heWJlIHdlIGNhbiBkZXNjcmliZSB0aGUgc2FtcGxlIGlucHV0IGhlcmUgYW5kIGhvdyB0byBkb3dubG9hZCBmcm9tIEdpdGh1YiwgSSd2ZSBzZWVuIHRoYXQgaW4gc29tZSBwYXBlcnMgcmF0aGVyIHRoYW4gZGVzY3JpYmluZyB0aGUgZ2VuZXJhbCBpbnB1dCBmb3JtYXQpDQoNCiAgcGNhRXhwbG9yZXIgbWFpbmx5IHJlcXVpcmVzIDMgaW5wdXQgZmlsZXMgaW4gdGV4dCBmb3JtYXQuIFRoZSBmaWxlcyBhcmUgZXhwZWN0ZWQgdG8gYmUgdGFiLXNlcGFyYXRlZCwgYnV0IGFsc28gY29tbWEtIG9yIHNlbWljb2xvbi1zZXBhcmF0ZWQgZmlsZXMgYXJlIGFjY2VwdGVkIChzZWUgKipBbHRlcm5hdGl2ZSBwcm90b2NvbCAxKiopLiBUaGUgZmlyc3QgaW5wdXQgZmlsZSBpcyB0aGUgY291bnQgbWF0cml4IHdoaWNoIHN0b3JlcyB0aGUgbnVtYmVyIG9mIHRpbWVzIChpLmUgY291bnRzKSBhIGNlcnRhaW4gZmVhdHVyZSAoZS5nIGdlbmUpIGlzIGZvdW5kIGluIGVhY2ggc2FtcGxlLiBJbiB0aGUgY291bnQgbWF0cml4LCB0aGUgc2FtcGxlcyBhcmUgc3RvcmVkIGluIHRoZSBjb2x1bW5zLCB3aGlsZSB0aGUgcm93cyBzdG9yZSB0aGUgaW5kaXZpZHVhbCBmZWF0dXJlcyAoc2VlIEZpZy4gMSkuDQogIA0KICAhWyoqRmlndXJlIDEqKiBFeGFtcGxlIG9mIGEgY291bnQgbWF0cml4IC0gVGhlIGZpZ3VyZSBzaG93cyB0aGUgZXhhbXBsZSBvZiBhIGNvdW50IG1hdHJpeCwgd2l0aCB0aGUgaW5kaXZpZHVhbCBmZWF0dXJlcyAoaGVyZSBnZW5lcykgaW4gdGhlIHJvd3MgYW5kIHRoZSBpbmRpdmlkdWFsIHNhbXBsZXMgaW4gdGhlIGNvbHVtbnMuIFRoZSBtYXRyaXggcmVwcmVzZW50cyBob3cgbWFueSB0aW1lcyBlYWNoIGZlYXR1cmUgd2FzIGZvdW5kIGluIGVhY2ggc2FtcGxlLiBUaGUgc2hvd24gY291bnQgbWF0cml4IGlzIGNvbW1hLXNlcGFyYXRlZCwgYnV0IGFsc28gc2VtaWNvbG9uLSBhbmQgdGFiLXNlcGFyYXRlZCBpbnB1dHMgYXJlIGFjY2VwdGVkIChzZWUgKipBbHRlcm5hdGl2ZSBwcm90b2NvbCAxKiopXShGaWd1cmVzX0Jhc2ljXzEvRmlndXJlIDEucG5nKQ0KDQogIFRoZSBzZWNvbmQgaW5wdXQgb2YgcGNhRXhwbG9yZXIgaXMgdGhlIG1ldGFkYXRhIGZpbGUuIFRoaXMgZmlsZSBzdG9yZXMgZm9yIGVhY2ggc2FtcGxlIHRoZSBuZWNlc3NhcnkgZXhwZXJpbWVudGFsIHZhcmlhYmxlcy4gVGhlIGluZGl2aWR1YWwgc2FtcGxlcyByZXByZXNlbnQgdGhlIHJvd3Mgb2YgdGhlIGZpbGUgd2hpbGUgdGhlIGNvbHVtbnMgc2F2ZSB0aGUgZGlmZmVyZW50IGV4cGVyaW1lbnRhbCB2YXJpYWJsZXMgKHNlZSBGaWcuIDIpLg0KICANCiAgIVsqKkZpZ3VyZSAyKiogRXhhbXBsZSBvZiBhIE1ldGFkYXRhIGZpbGUgLSBUaGUgZmlndXJlIHNob3dzIHRoZSBleGFtcGxlIG9mIGEgTWV0YWRhdGEgZmlsZS4gVGhlIHJvd3Mgb2YgdGhlIGZpbGUgY29udGFpbiB0aGUgaW5kaXZpZHVhbCBzYW1wbGVzIHdoaWxlIHRoZSBjb2x1bW5zIHJlcHJlc2VudCByZWxldmFudCBleHBlcmltZW50YWwgdmFyaWFibGVzLiBUaGUgdmFyaWFibGUgY2FuIGNoYW5nZSBkZXBlbmRpbmcgb24gdGhlIGRhdGEgc2V0IGFuZCByZXNlYXJjaCBxdWVzdGlvbi5dKEZpZ3VyZXNfQmFzaWNfMS9GaWd1cmUgMi5wbmcpDQogIExhc3RseSwgdGhlIHRoaXJkIGlucHV0IG9mIHBjYUV4cGxvcmVyIGlzIG9wdGlvbmFsLCBidXQgaGlnaGx5IHJlY29tbWVuZGVkIGZvciBhbiBlYXNlIG9mIGludGVycHJldGF0aW9uIG9mIHRoZSByZXN1bHRzLiBUaGUgbGFzdCBpbnB1dCBpcyB0aGUgYW5ub3RhdGlvbiBmaWxlLiBUaGUgZmlsZSBjb250YWlucyB0aGUgZmVhdHVyZSBpZHMgb2YgdGhlIGNvdW50IG1hdHJpeCBpbiB0aGUgcm93cyBhbmQgYXQgbGVhc3Qgb25lIGNvbHVtbiBjYWxsZWQgZ2VuZSBuYW1lIHdoaWNoIGNvbnRhaW5zIGEgbW9yZSBodW1hbiByZWFkYWJsZSBmb3JtIG9mIHRoZSBmZWF0dXJlIGlkcyAoZS5nLiBIR05DIGdlbmUgbmFtZXMgW2h0dHBzOi8vZG9pLm9yZy8xMC4xMDkzL25hci9na2FhOTgwXSBpZiB0aGUgZmVhdHVyZXMgYXJlIGdlbmUgaWRzKS4gRmlnLiAzIHNob3dzIGFuIGV4YW1wbGUgb2YgYW4gYW5ub3RhdGlvbiBmaWxlLg0KICANCiAgIVsqKkZpZ3VyZSAzKiogRXhhbXBsZSBvZiBhbiBhbm5vdGF0aW9uIGZpbGUgLSBUaGUgYW5ub3RhdGlvbiBmaWxlIGNvbnRhaW5zIGEgcm93IGZvciBlYWNoIG9mIHRoZSBmZWF0dXJlcyBvZiB0aGUgY291bnQgbWF0cml4LiBGdXJ0aGVybW9yZSwgdGhlIGZpbGUgY29udGFpbnMgYXQgbGVhc3Qgb25lIGNvbHVtbiBjYWxsZWQgZ2VuZSBuYW1lcyB3aGljaCBjb250YWlucyBhIG1vcmUgaHVtYW4gcmVhZGFibGUgZm9yIG9mIHRoZSBmZWF0dXJlIGlkZW50aWZpZXJzIG9mIHRoZSByb3dzLiBJbiB0aGUgc2hvd24gZXhhbXBsZSB0aGUgZmVhdHVyZSBpZHMgYXJlIEVOU0VNQkwgaWRzIHdoaWxlIHRoZSBjb2x1bW4gZ2VuZSBuYW1lcyBjb250YWlucyBIR05DIGdlbmUgbmFtZXMuIF0oRmlndXJlc19CYXNpY18xL0ZpZ3VyZSAzLnBuZykNCg0KKkV4cGxvcmluZyB0aGUgZGF0YSB3aXRoIHBjYUV4cGxvcmVyKiANCg0KQmVmb3JlIHdlIHN0YXJ0IHdpdGggdGhlIGV4cGxvcmF0aW9uIG9mIHRoZSBkYXRhLCB0aGUgbmVjZXNzYXJ5IHBhY2thZ2VzIGFuZCBkZXBlbmRlbmNpZXMgbmVlZCB0byBiZSBpbnN0YWxsZWQgYW5kIGxvYWRlZC4gKipTdXBwb3J0IFByb3RvY29sIDEqKiBkZXNjcmliZXMgaG93IHRvIGluc3RhbGwgYW5kIGxvYWQgdGhlIHBhY2thZ2VzLiANCg0KMS4gUHJlcGFyZSB0aGUgaW5wdXQgZGF0YS4gTGF1bmNoIHRoZSBTaGlueSBhcHBsaWNhdGlvbiB3aXRoIHRoZSBjb21tYW5kIGBwY2FFeHBsb3Jlcihjb3VudG1hdHJpeCwgbWV0YWRhdGEsIGFubm90YXRpb24pYCB3aGVyZSBgY291bnRtYXRyaXhgLCBgbWV0YWRhdGFgIGFuZCBgYW5ub3RhdGlvbmAgaGF2ZSB0byBiZSBzdWJzdGl0dXRlZCBieSB0aGUgZmlsZSBwYXRocyBvZiB0aGUgcmVzcGVjdGl2ZSBpbnB1dCBmaWxlcy4gVG8gbGF1bmNoIHRoZSBhcHBsaWNhdGlvbiwgZW50ZXIgdGhlIGNvbW1hbmQgaW50byB0aGUgY29uc29sZSBvZiBSU3R1ZGlvIGFuZCBwcmVzcyB0aGUgRW50ZXItQnV0dG9uLiBUaGlzIHNob3VsZCBsYXVuY2ggYSBzZWNvbmQgd2luZG93IHdpdGggdGhlIHBjYUV4cGxvcmVyIGFwcGxpY2F0aW9uLiBJbiB0aGlzIGFwcGxpY2F0aW9uIHlvdSBzaG91bGQgc2VlIHRoZSBEYXRhIFVwbG9hZCBwYW5lbCBhcyBzaG93biBpbiBGaWcuIDQuDQoNCiFbKipGaWd1cmUgNCoqIERhdGEgVXBsb2FkIHBhbmVsIC0gVGhlIGZpZ3VyZSBzaG93cyB0aGUgRGF0YSBVcGxvYWQgcGFuZWwgd2hpY2ggaXMgdGhlIGZpcnN0IHBhbmVsIGEgdXNlciBzZWVzIHVwb24gbGF1bmNoaW5nIHBjYUV4cGxvcmVyLiBUaGUgcGFuZWwgcHJvdmlkZXMgcHJldmllcyBvbiB0aGUgaW5wdXQgZGF0YSBhcyB3ZWxsIGFzIGJ1dHRvbnMgdG8gaW50ZXJhY3Qgd2l0aCB0aGUgYXBwbGljYXRpb24uXShGaWd1cmVzX0Jhc2ljXzEvRmlndXJlIDQucG5nKQ0KDQoyLiBDbGljayB0aGUgIkdlbmVyYXRlIHRoZSBkZHMgYW5kIGRzdCBvYmplY3QiIGJ1dHRvbiB0byBnZW5lcmF0ZSB0aGUgZGRzIGFuZCBkc3Qgb2JqZWN0IG5lZWRlZCBmb3IgdGhlIGV4cGxvcmF0aW9uIG9mIHRoZSBkYXRhIChGaWcgNCkuIFNjcm9sbCBkb3duIG9uIHRoZSBEYXRhIFVwbG9hZCBwYW5lbC4gQWZ0ZXIgdGhlIGdlbmVyYXRpb24gb2YgdGhlIGRkcyBhbmQgZHN0IG9iamVjdCB5b3Ugc2hvdWxkIGZpbmQgdGhlICdTZWxlY3Qgb25lIG9mIHRoZSBmb2xsb3dpbmcgdHJhbnNmb3JtYXRpb25zIGZvciB5b3VyIGRhdGE6JyBvcHRpb24gd2l0aCB0aHJlZSBibHVlIGNvbG9yZWQgYnV0dG9ucyB1bmRlcm5lYXRoLiBFYWNoIGJ1dHRvbiBkZXNjcmliZXMgYSBkaWZmZXJlbnQgdHJhbnNmb3JtYXRpb24gb2YgdGhlIGRhdGEuIFRoZSBmaXJzdCBidXR0b24gb24gdGhlIGZhciBsZWZ0ICdDb21wdXRlIHZhcmlhbmNlIHN0YWJpbGl6ZWQgdHJhbnNmb3JtZWQgZGF0YSBmcm9tIHRoZSBgZGRzYCBvYmplY3QnIGNvbXB1dGVzIGEgdmFyaWFuY2Ugc3RhYmlsaXplZCB0cmFuc2Zvcm1lZCB2ZXJzaW9uIG9uIHRoZSBkYXRhIHVwb24gY2xpY2tpbmcgdGhlIGJ1dHRvbi4gVGhlIG1pZGRsZSBidXR0b24gY29tcHV0ZXMgYSByZWd1bGFyaXplZCBsb2dhcml0aG0gdHJhbnNmb3JtZWQgdmVyc2lvbiBvZiB0aGUgZGF0YSwgd2hpbGUgdGhlIGJ1dHRvbiBvbiB0aGUgZmFyIHJpZ2h0IGNvbXB1dGVzIGxvZzIgZGF0YS4gVGhlIGNob2ljZSBvZiB0cmFuc2Zvcm1hdGlvbiBvZiB0aGUgZGF0YSBpbiB0aGlzIHN0ZXAgc2hvdWxkIGJlIGRlcGVuZGVudCBvbiB0aGUgaW5wdXQgZGF0YS4gSWYgeW91IGZvbGxvdyB0aGlzIHByb3RvY29sIHVzaW5nIHRoZSBwcm92aWRlZCBzYW1wbGUgZGF0YSwgY2xpY2sgdGhlICdDb21wdXRlIHZhcmlhbmNlIHN0YWJpbGl6ZWQgdHJhbnNmb3JtZWQgZGF0YSBmcm9tIHRoZSBgZGRzYCBvYmplY3QnIGJ1dHRvbiBvbiB0aGUgZmFyIGxlZnQuIA0KDQozLiBBdCB0aGUgYm90dG9tIG9mIHRoZSBEYXRhIFVwbG9hZCBwYW5lbCwgYSBwcmV2aWV3IG9mIHRoZSBpbnB1dCBkYXRhIGlzIHByb3ZpZGVkLiBIZXJlIHlvdSdsbCBmaW5kIGZvdXIgZ3JlZW4gY29sb3JlZCBidXR0b25zIHdoaWNoIHByb3ZpZGUgYSBwcmV2aWV3IG9uIHRoZSByZXNwZWN0aXZlIGlucHV0IGRhdGEgdXBvbiBjbGlja2luZy4gDQoNCjQuIE5hdmlnYXRlIHRvIHRoZSBDb3VudHMgVGFibGUgcGFuZWwgdGhyb3VnaCBjbGlja2luZyBvbiB0aGUgcGFuZWwgbmFtZSBpbiB0aGUgcGFuZWwgbGlzdCBhdCB0aGUgYmVnaW5uaW5nIG9mIGVhY2ggcGFuZWwgKEZpZy4gNSkuIEluIHRoaXMgcGFuZWwsIHRoZSBjb3VudCBpbmZvcm1hdGlvbiBvZiB0aGUgY291bnQgbWF0cml4IGlzIHNob3duIGluIGEgdGFibGUuIEEgZHJvcC1kb3duIG1lbnUgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgcGFuZWwgcHJvdmlkZXMgdGhlIHBvc3NpYmlsaXR5IHRvIGNoYW5nZSB0aGUgZGF0YSBzY2FsZSBpbiB0aGUgdGFibGUuIERpZmZlcmVudCBvcHRpb25zIGNhbiBiZSBjaG9zZW4gdGhyb3VnaCBjbGlja2luZyAoZS5nLiByYXcgY291bnRzLCBub3JtYWxpemVkIGNvdW50cywgcmVndWxhcml6ZWQgbG9nYXJpdGhtIHRyYW5zZm9ybWVkIGNvdW50cywgZXRjLikuIFVzZXJzIGNhbiBkb3dubG9hZCB0aGUgY291bnRzIHRhYmxlIHRocm91Z2ggY2xpY2tpbmcgb24gdGhlIGdyZWVuIGRvd25sb2FkIGJ1dHRvbiBiZWxvdyB0aGUgdGFibGUgKEZpZy4gNSkuDQoNCiFbKipGaWd1cmUgNSoqIENvdW50cyBUYWJsZSBwYW5lbCAtIFRoZSBmaWd1cmUgc2hvd3MgdGhlIENvdW50cyBUYWJsZSBwYW5lbC4gVGhpcyBwYW5lbCBwcm92aWRlcyBhbiBvdmVydmlldyBvZiB0aGUgaW5wdXQgY291bnRzIG1hdHJpeC5dKEZpZ3VyZXNfQmFzaWNfMS9GaWd1cmUgNS5wbmcpDQoNCjUuIFNjcm9sbCBkb3duIHVudGlsIHlvdSBzZWUgdGhlICdTYW1wbGUgdG8gc2FtcGxlIHNjYXR0ZXIgcGxvdHMnIGhlYWRpbmcgKEZpZy4gNSkuIENob29zZSAncGVhcnNvbicgYXMgY29ycmVsYXRpb24gbWV0aG9kIGZyb20gdGhlICdDb3JyZWxhdGlvbiBtZXRob2QgcGFsZXR0ZScuIEVuc3VyZSB0aGF0IGJvdGggb3B0aW9ucyAnVXNlIGxvZzIgdmFsdWVzIGZvciBwbG90IGF4ZXMgYW5kIHZhbHVlcycgYW5kICdVc2UgYSBzdWJzZXQgb2YgbWF4IDEwMDAgZ2VuZXMgKHF1aWNrZXIgdG8gcGxvdCknIGFyZSBzZWxlY3RlZC4gQW4gb3B0aW9uIGlzIHNlbGVjdGVkLCBpZiB0aGUgc21hbGwgYm94IGluIGZyb250IG9mIHRoZSBvcHRpb24gaXMgdGlja2VkIChGaWcuIDUpLiBDbGljayBvbiB0aGUgJ1J1bicgYnV0dG9uIHRvIGdlbmVyYXRlIHRoZSBzY2F0dGVyIHBsb3RzLiANCg0KNi4gKlRPRE86IFNvbWV0aGluZyBhYm91dCB0aGUgaW5zcGVjdGlvbiBvZiB0aGUgcGxvdCBhbmQgc29tZSBnZW5lcmFsIHJlbWFya3MgdG8gdGhlIHR5cGUgb2YgcGxvdHMqDQoNCiFbKipGaWd1cmUgNioqXShGaWd1cmVzX0Jhc2ljXzEvRmlndXJlIDYucG5nKQ0KDQohWyoqRmlndXJlIDcqKiBTYW1wbGUgdG8gU2FtcGxlIHNpbWlsYXJpdHkgaGVhdG1hcF0oRmlndXJlc19CYXNpY18xL0ZpZ3VyZSA3LnBuZykNCg0KNy4gTmF2aWdhdGUgdG8gdGhlIERhdGEgT3ZlcnZpZXcgcGFuZWwgdGhyb3VnaCBjbGlja2luZyBvbiB0aGUgcGFuZWwgbmFtZSBpbiB0aGUgcGFuZWwgbGlzdCBhdCB0aGUgYmVnaW5uaW5nIG9mIGVhY2ggcGFuZWwgKEZpZy4gOCkuIFRoZSBwYW5lbCBzaG93cyB0aGUgaW5wdXQgbWV0YWRhdGEgYXMgdGFibGUgaW4gdGhlIHVwcGVyIGhhbGYgb2YgdGhlIHBhbmVsLiBUaGUgbnVtYmVyIG9mIGVudHJpZXMgc2hvd24gaW4gdGhlIHRhYmxlIGNhbiBiZSBtYW5hZ2VkIHdpdGggdGhlICJTaG93IFggZW50cmllcyIgZHJvcCBkb3duIG1lbnUuIEZ1cnRoZXJtb3JlLCBpbiB0aGUgcmlnaHQgdXBwZXIgY29ybmVyIG9mIHRoZSB0YWJsZSwgdXNlcnMgY2FuIGZpbmQgYSBTZWFyY2ggZmllbGQsIHdoaWNoIGNhbiBiZSB1c2VkIHRvIHNlYXJjaCBmb3Igc3BlY2lmaWMgdGVybXMgaW4gdGhlIG1ldGFkYXRhIHRhYmxlIChGaWcuIDgpLiBCZWxvdyB0aGUgbWV0YWRhdGEgdGFibGUsIGEgU2FtcGxlIHRvIFNhbXBsZSBkaXN0YW5jZSBoZWF0bWFwIGNhbiBiZSBmb3VuZC4gVGhpcyBoZWF0bWFwIHJlZmxlY3RzIHRoZSBkaXN0YW5jZXMgYmV0d2VlbiB0aGUgaW5kaXZpZHVhbCBzYW1wbGVzLiBUaGUgIlNlbGVjdCB0aGUgZGlzdGFuY2UgbWV0aG9kIHRvIHVzZSIgb3B0aW9uIGVuYWJsZXMgdXNlcnMgdG8gY2hhbmdlIHRoZSBkaXN0YW5jZSBtZXRob2QgdXNlZCBmb3IgdGhlIGhlYXRtYXAuIEZ1cnRoZXJtb3JlLCB1c2VycyBoYXZlIHRoZSBvcHRpb24gdG8gZG93bmxvYWQgdGhlIGhlYXRtYXAgdmlhIHRoZSAiRG93bmxvYWQgUGxvdCIgYnV0dG9uIGluIHRoZSBsb3dlciByaWdodCBjb3JuZXIgYmVsb3cgdGhlIGhlYXRtYXAuIEluIHRoZSBmaWVsZCAiU2F2ZSBhcy4uLiIgdXNlcnMgY2FuIHNwZWNpZnkgdGhlIG5hbWUgb2YgdGhlIGZpbGUgdG8gc2F2ZSB0aGUgaGVhdG1hcCAoRmlnIDgpLiANCg0KIVsqKkZpZ3VyZSA4KipdKEZpZ3VyZXNfQmFzaWNfMS9GaWd1cmUgOC5wbmcpDQoNCjguIFNjcm9sbCBkb3duIGluIHRoZSBEYXRhIE92ZXJ2aWV3IHBhbmVsLiBCZWxvdyB0aGUgaGVhdG1hcCwgdGhlIHBhbmVsIHByb3ZpZGVzIGZ1cnRoZXIgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGlucHV0IGRhdGEgKEZpZy4gOSAmIDEwKS4NCg0KIVsqKkZpZ3VyZSA5KipdKEZpZ3VyZXNfQmFzaWNfMS9GaWd1cmUgOS5wbmcpDQoNCiFbKipGaWd1cmUgMTAqKl0oRmlndXJlc19CYXNpY18xL0ZpZ3VyZSAxMC5wbmcpDQoNCjkuIE5hdmlnYXRlIHRvIHRoZSBTYW1wbGVzIFZpZXcgcGFuZWwgdGhyb3VnaCBjbGlja2luZyBvbiB0aGUgcGFuZWwgbmFtZSBpbiB0aGUgcGFuZWwgbGlzdCBhdCB0aGUgYmVnaW5uaW5nIG9mIGVhY2ggcGFuZWwgKEZpZy4gMTEpLiBXaGVuIGRpcmVjdGVkIHRvIHRoZSBwYW5lbHMsIHVzZXJzIHNlZSB0aGUgUENBIG9mIHRoZSBpbmRpdmlkdWFsIHNhbXBsZXMgb2YgdGhlIGlwdXQgZGF0YSBvbiB0aGUgbGVmdCBzaWRlIHdpdGggdGhlIGNvcnJlc3BvbmRpbmcgc2NyZWUgcGxvdCBzaG93biBvbiB0aGUgcmlnaHQgc2lkZS4gSW5pdGlhbGx5IHRoZSBzYW1wbGVzIHNob3duIGluIHRoZSBQQ0EgYXJlIG5vdCBjb2xvcmVkIGJ5IGFueSBncm91cCBoZW5jZSBpdCBpcyBoYXJkIHRvIGlkZW50aWZ5IHRoZSBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIHNhbXBsZXMgYWxvbmcgd2hpY2ggdGhlIFBDQSBncm91cHMgdGhlIHNhbXBsZXMuIEluIHRoZSBwcmVzZW50ZWQgZGF0YSwgdXNlcnMgc2hvdWxkIGNvbG9yIHRoZSBzYW1wbGVzIGJ5IGNvbmRpdGlvbi4gVG8gY29sb3IgdGhlIHNhbXBsZXMgYnkgY29uZGl0aW9uLCBjbGljayBvbiB0aGUgIkdyb3VwL2NvbG9yIGJ5IiBmaWxlZCBvbiB0aGUgZ3JleSBzaWRlIGJhciBhdCB0aGUgZmFyIGxlZnQgb2YgdGhlIHNjcmVlbi4gU2Nyb2xsIGRvd24gaW4gdGhlIGRyb3AtZG93biBtZW51IHdoaWNoIG9wZW5zIHVwb24gY2xpY2tpbmcgdW50aWwgeW91IGZpbmQgdGhlICJjb25kaXRpb24iIG9wdGlvbi4gQ2xpY2sgdGhpcyBvcHRpb24uIEl0IHNob3VsZCBub3cgYmUgZGlzcGxheWVkIGluIHRoZSBiZWZvcmUgZW1wdHkgZmllbGQgKEZpZy4gMTIpLiBGdXJ0aGVybW9yZSwgdGhlIFBDQSBwbG90IGNoYW5nZWQgZGlzcGxheWluZyB0aGUgc2FtcGxlcyBub3cgaW4gNCBjb2xvcnMgY29tcGFyZWQgdG8gb25lIGJlZm9yZSAoRmlnLiAxMikuIFVzZXJzIGNhbiBhbHNvIGRvd25sb2FkIHRoZSBQQ0EgcGxvciB2aWEgdGhlICJEb3dubG9hZCBwbG90IiBidXR0b24gaW4gdGhlIGxvd2VyIHJpZ2h0IGNvcm5lciBvZiB0aGUgcGxvdC4gQXMgc2VlbiBiZWZvcmUsIHVzZXJzIGNhbiBzcGVjaWZ5IHRoZSBuYW1lIG9mIHRoZSBmaWxlIHRoZXkgd2FudCB0byBzYXZlIHRoZSBwbG90LiBUaGlzIGlzIGFsc28gcG9zc2libGUgZm9yIHRoZSBTY3JlZXBsb3Qgb24gdGhlIHJpZ2h0IHNpZGUgb2YgdGhlIHBhbmVsLiANCg0KICAqc29tZSBub3RlcyBhYm91dCBob3cgdG8gZGVsZXRlIG9wdGlvbiwgaWRlbnRpZml5IHRoZSByaWdodCBvcHRpbyBmb3IgeW91IGRhdGEgYW5kIGhvdyB0byB1c2UgdGhlIHNjcmVlIHBsb3QqDQoNCg0KIVsqKkZpZ3VyZSAxMSoqIFRoZSBTYW1wbGVzIFZpZXcgcGFuZWwgLSBUaGlzIHBhbmVsIHNob3dzIGEgUENBIG9mIHRoZSBpbmRpdmlkdWFsIHNhbXBsZXMgb2YgdGhlIGlucHV0IGRhdGEuIEluIHRoZSB1cHBlciBwYXJ0IG9mIHRoZSBwYW5lbCwgdGhlIFBDQSBvbiB0aGUgc2FtcGxlcyBhbmQgdGhlIGNvcnJlc3BvbmRpbmcgc2NyZWUgcGxvdCBhcmUgc2hvd24uIEluaXRpYWxseSB0aGVyZSBpcyBubyBncm91cGluZyBzaG93biBpbiB0aGUgUENBLl0oRmlndXJlc19CYXNpY18xL0ZpZ3VyZSAxMS5wbmcpDQoNCiFbKipGaWd1cmUgMTIqKiBQQ0EgY29sb3JlZCBieSBjb25kaXRpb24gLSBUaGUgUENBIHBsb3Qgb2YgdGhlIHNhbXBsZXMgaXMgc2hvd24gY29sb3JlZCBieSBjb25kaXRpb24uIFRoaXMgY29sb3JpbmcgaXMgYWNoaWV2ZWQgYnkgc2VsZWN0aW5nIHRoZSBvcHRpb24gImNvbmRpdGlvbiIgaW4gdGhlICJHcm91cC9jb2xvciBieSIgc2VsZWN0aW9uIHRhYiBhdCB0aGUgZmFyIGxlZnQgb2YgdGhlIHNjcmVlbi4gVGhlIHRhYiBpbmRpY2F0ZXMgdGhlIHNlbGVjdGVkIG9wdGlvbiBieSBkaXNwbGF5aW5nIHRoZSBuYW1lIG9mIHRoZSBvcHRpb24gaW4gdGhlIGZpZWxkLiBVc2VycyBjYW4gcmVtb3ZlIG9wdGlvbnMgYnkgY2xpY2tpbmcgaW50byB0aGUgb3B0aW9uIGZpZWxkIHJpZ2h0IGJlaGluZCB0aGUgb3B0aW9uIHRvIGJlIGRlbGV0ZWQgYW5kIGhpdHRpbmcgdGhlIGRlbGV0ZSBrZXkgb24gdGhlIGtleWJvYXJkLl0oRmlndXJlc19CYXNpY18xL0ZpZ3VyZSAxMi5wbmcpDQoNCjEwLiBUaGUgU2FtcGxlIFZpZXcgcGFuZWwgcHJvdmlkZXMgdGhlIHBvc3NpYmlsaXR5IHRvIHpvb20gaW4gb24gdGhlIFBDQS4gRm9yIHRoaXMsIGhvdmVyIHlvdXIgbW91c2Ugb3ZlciB0aGUgUENBIHBsb3QgdW50aWwgeW91ciBtb3VzZSBwb2ludGVyIGNoYW5nZXMgdG8gYSBsaXR0bGUgcGx1cyBzaWduLiBQcmVzcyB0aGUgbGVmdCBidXR0b24gb2YgdGhlIG1vdXNlIGFuZCBtb3ZlIHRoZSBtb3VzZSB0byBkcmF3IGEgbGl0dGxlIGdyZXkgcmVjdGFnbGUgKEZpZy4gMTMpLiBNb3ZlIHRoZSBtb3VzZSB0byB0aGUgdXBwZXIgbGVmdCBjb3JuZXIgb2YgdGhlIFBDQSBwbG90IGFuZCBzZWxlY3QgYWxsIHNhbXBsZXMgYmVsb25naW5nIHRvIHRoZSBuYWl2ZSBjb25kaXRpb24gKGNvbG9yZWQgaW4gYmx1ZSBpbiBGaWcuIDEyKSBhcyBleHBsYWluZWQgYmVmb3JlLiBBZnRlciBzZWxlY3RpbmcgdGhlIHNhbXBsZXMsIHNjcm9sbCBkb3duIGluIHRoZSBwYW5lbCB1bnRpbCB5b3Ugc2VlIGEgem9vbWVkIGluIHZlcnNpb24gb2YgdGhlIFBDQSBwbG90IGNvbnRhaW5pbmcgbWFpbmx5IHRoZSBzZWxlY3RlZCBzYW1wZWxzLiBUaGlzIHNob3VsZCBzb21ld2hhdCBsb29rIGxpa2UgdGhlIHBsb3Qgc2hvd24gaW4gRmlnLiAxMy4gDQoNCg0KIVsqKkZpZ3VyZSAxMyoqIFpvb21lZCBpbiBQQ0EgcGxvdCAtIFRoZSBmaWd1cmUgc2hvd3MgdGhlIHpvb21pbmcgbWVjaGFuaXNtIG9uIHRoZSBQQ0EgcGxvdCBvZiB0aGUgU2FtcGxlcyBWaWV3IHBhbmVsLiBUaGUgZ3JleSByZWN0YW5nbGUgaW4gdGhlIHVwcGVyIFBDQSBwbG90IGluZGljYXRlcyB0aGUgcG9ydGlvbiBvZiB0aGUgUENBIHBsb3Qgc2VsZWN0ZWQgZm9yIHpvb21pbmcuIFRoaXMgc2VsZWN0ZWQgcG9ydGlvbiBvZiB0aGUgcGxvdCBpcyBzaG93biBpbiB0aGUgbG93ZXIgUENBIHBsb3QgaW4gbW9yZSBkZXRhaWwuXShGaWd1cmVzX0Jhc2ljXzEvRmlndXJlIDEzLnBuZykNCg0KMTQuIFRoZSB6b29tZWQgaW4gUENBIHBsb3QgY2FuIGJlIGRvd25sb2FkZWQgdmlhIHRoZSAiRG93bmxvYWQgcGxvdCIgYnV0dG9uIGluIHRoZSBsb3dlciByaWdodCBjb3JuZXIgYmVsb3cgdGhlIHBsb3QuIEFzIGFmb3JlbWVudGlvbmVkIHRoZSBuYW1lIG9mIHRoZSBmaWxlIHRvIHNhdmUgdGhlIHBsb3QgY2FuIGFsc28gYmUgc3BlY2lmaWVkLg0KDQoxNS4gKlNvbWV0aGluZyBhYm91dCB0aGUgcGxvdCBvbiB0aGUgcmlnaHQgc2llZCBvZiB0aGUgem9vbWVkIGluIFBDQSoNCg0KMTYuIFNjcm9sbCBkb3duIGluIHRoZSBTYW1wbGUgVmlldyBwYW5lbCB1bnRpbCB5b3Ugc2VlIHRoZSAiT3V0bGllciBpZGVudGlmaWNhdGlvbiIgb3B0aW9uIChGaWcuIDE0KS4gVGhlICJTZWxlY3Qgd2hpY2ggc2FtcGxlKHMpIHRvIHJlbW92ZSAtIHN1c3BlY3RlZCBvdXRsaWVycyIgb3B0aW9ucyBwcm92aWRlcyB0aGUgcG9zc2liaWxpdHkgdG8gc2VsZWN0IGluZGl2aWR1YWwgc2FtcGxlcywgd2hpY2ggYXJlIHN1c3BlY3RlZCB0byBiZSBvdXRsaWVycywgYW5kIHJlbW92ZSB0aGVtIGZyb20gdGhlIFBDQS4gRm9yIGRlbW9uc3RyYXRpb24gcHVycG9zZXMgc2VsZWN0IGFsbCBzYW1wbGVzIGZyb20gdGhlICJuYWl2ZSIgY29uZGl0aW9uIGFuZCByZW1vdmUgdGhlbSBmcm9tIHRoZSBQQ0EgKHRoZSBzYW1wbGUgaWRzIGVuZCBpbiAiMTAyIiwgIjExMSIsICIxODIiLCAiMjYyIiwgIjI4NCIgYW5kICIzNjgiKS4gVG8gcmVtb3ZlIHNhbXBsZXMgZnJvbSB0aGUgcGxvdCwgY2xpY2sgb24gdGhlIGZpZWxkIGJlbG93IHRoZSAiU2VsZWN0IHdoaWNoIHNhbXBsZShzKSB0byByZW1vdmUgLSBzdXNwZWN0ZWQgb3V0bGllcnMiIG9wdGlvbi4gVGhpcyBvcGVucyBhIGRyb3Atd29uIG1lbnUgd2l0aCB0aGUgc2FtcGxlIGlkcyBvZiBhbGwgc2FtcGxlcyBsaXN0ZWQuIFNlbGVjdCB0aGUgYWJvdmUgbWVudGlvbmVkIHNhbXBsZSBpZHMgdW50aWwgdGhlIFBDQSBwbG90IGxvb2tzIGxpa2UgRmlnLiAxNS4NCg0KICAqU29tZXRoaW5nIGFib3V0IHRoZSBwbG90IGF0IHRoZSBib3R0b20gb2YgdGhlIHBhbmVsIGFuZCBvdmVyYWxsIG91dGxpZXIgaWRlbnRpZmljYXRpb24qDQoNCiFbKipGaWd1cmUgMTQqKiBPdXRsaWVyIGlkZW50aWZpY2F0aW9uIC0gVGhlIFNhbXBsZXMgVmlldyBwYW5lbCBwcm92aWRlcyB0aGUgcG9zc2liaWxpdHkgdG8gZGV0ZWN0IG91dGxpZXJzLl0oRmlndXJlc19CYXNpY18xL0ZpZ3VyZSAxNC5wbmcpDQoNCiFbKipGaWd1cmUgMTUqKiBQQ0EgcGxvdCB3aXRoIG91dGxpZXJzIHJlbW92ZWQgLSBUSGUgZmlndXJlcyBzaG93cyB0aGUgUENBIHBsb3Qgd2l0aCBhbGwgc2FtcGxlcyBvZiB0aGUgIm5haXZlIiBjb25kaXRpb24gcmVtb3ZlZC4gV2l0aCB0aGlzIHR5cGUgb2Ygc2FtcGxlIHNlbGVjdGlvbiwgb3V0bGllciBzYW1wbGVzIGluIHRoZSBkYXRhIGNhbiBiZSBkZXRlY3RlZCBhbmQgcmVtb3ZlZCBmcm9tIHRoZSBQQ0EuXShGaWd1cmVzX0Jhc2ljXzEvRmlndXJlIDE1LnBuZykNCg0KMTcuIE5hdmlnYXRlIHRvIHRoZSAiSW50cnVjdGlvbnMiIHBhbmVsIHRocm91Z2ggY2xpY2tpbmcgb24gdGhlIHBhbmVsIG5hbWUgaW4gdGhlIHBhbmVsIGxpc3QgYXQgdGhlIGJlZ2lubmluZyBvZiBlYWNoIHBhbmVsIChGaWcuIDE2KS4gT3BlbiB0aGUgdmlnbmV0dGVzIG9mIHBjYUV4cGxvcmVyIGJ5IGNsaWNraW5nIG9uIHRoZSB0d28gYnV0dG9ucyAiT3BlbiB0aGUgVXNlciBHdWlkZSAobWFpbiB2aWduZXR0ZSkiIGFuZCAiT3BlbiB0aGUgJ1VQIGFuZCBSdW5uaW5nJyB2aWduZXR0ZSIuIFRoaXMgd2lsbCBvcGVuIHRoZSB0d28gdmlnbmV0dGVzIG9mIHBjYUV4cGxvcmVyIGluIHlvdXIgc2VsZWN0ZWQgZGVmYXVsdCBicm93c2VyLiBUaGUgdmlnbmV0dGVzIGRlc2NyaWJlIHRoZSBpbmRpdmlkdWFsIHBhbmVscyBvZiBwY2FFeHBsb3JlciBpbiBkZXRhaWwgYW5kIHByb3ZpZGUgd2Fsa3Rocm91Z2hzIG9uIGhvdyB0byBleHBsb3JlIGlucHV0IGRhdGEgd2l0aCBwY2FFeHBsb3Jlci4gVXNlcnMgYXJlIHJlY29tbWVuZGVkIHRvIHJlYWQgdGhlIHZpZ25ldHRlcyB0byBmdWxseSBncmFwcyB0aGUgZGlmZmVyZW50IHBvc3NpYmlsaXRpZXMgcHJvdmlkZWQgd2l0aCBwY2FFeHBsb3Jlci4NCg0KIVsqKkZpZ3VyZSAxNioqIEluc3RydWN0aW9ucyBwYW5lbF0oRmlndXJlc19CYXNpY18xL0ZpZ3VyZSAxNi5wbmcpDQoNCg0KIyBTZXNzaW9uIGluZm9ybWF0aW9uIHstfQ0KDQpgYGB7cn0NCnNlc3Npb25JbmZvKCkNCmBgYA0K